package hu.mapro.model.analyzer;

import hu.mapro.model.descriptor.Generate;
import hu.mapro.model.generator.AutoBeanGenerator;
import hu.mapro.model.generator.Generator;

import java.lang.annotation.Annotation;
import java.util.Iterator;
import java.util.Set;

import org.aspectj.lang.annotation.Aspect;
import org.reflections.Reflections;
import org.reflections.scanners.SubTypesScanner;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;
import org.reflections.util.FilterBuilder;

import com.google.common.collect.Sets;
import com.sun.codemodel.JClassContainer;
import com.sun.codemodel.JCodeModel;

public class ClassPathGenerator implements Generator {

	ClassLoader classLoader;
	
	public ClassPathGenerator(ClassLoader classLoader) {
		super();
		this.classLoader = classLoader;
	}

	public void generate(final Generate model, JClassContainer classContainer) {
		JCodeModel cm = classContainer.owner();
		AutoBeanGenerator generator = new AutoBeanGenerator(cm);

		FilterBuilder fb = new FilterBuilder();
		ConfigurationBuilder cb = new ConfigurationBuilder();
		for (String p : model.getSourcePackage()) {
			fb.include(FilterBuilder.prefix(p));
			cb.addUrls(ClasspathHelper.forPackage(p, classLoader));
		}
		cb.filterInputsBy(fb);
		cb.setScanners(new SubTypesScanner(false));
		
		cb.addClassLoader(classLoader);

		Reflections reflections = new Reflections(cb);

		
		
		Set<Class<? extends Object>> classes = Sets.newHashSet();
		classes.addAll(reflections.getSubTypesOf(Object.class));
		classes.addAll(reflections.getSubTypesOf(Enum.class));
		
		//List<Class<? extends Object>> classes = ReflectionUtils.forNames(reflections.getResources(Pattern.compile(".*\\.class")), cb.getClassLoaders());
		
		Iterator<Class<?>> it = classes.iterator();
		
		while (it.hasNext()) {
			Class<?> cl = it.next();
			
			for (Annotation a : cl.getAnnotations()) {
				if (a.annotationType().getName().equals(Aspect.class.getName())) {
					it.remove();
					break;
				}
			}
		}
		
		ModelAnalyzer analyzer = new ModelAnalyzer(
				classes.toArray(new Class[0])
		);		
		
		
		generator.generateFields(classContainer, cm.directClass(model.getServiceClass()), analyzer.getDefinedTypes(), analyzer.getExtraInfo());

		
	}

}
